package cn.geminis.lowcode.processor;

import cn.geminis.lowcode.annotation.ExcelController;
import cn.geminis.lowcode.compiler.code.*;
import cn.geminis.lowcode.utils.Flags;
import cn.geminis.lowcode.utils.Utils;
import lombok.SneakyThrows;

import javax.lang.model.element.Element;
import java.lang.annotation.Annotation;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

/**
 * @author puddi
 */
public class ExcelControllerProcessor extends AbstractControllerProcessor {

    private String entityQualifiedName;
    private String filterName;

    @Override
    public Class<? extends Annotation> getSupportAnnotation() {
        return ExcelController.class;
    }

    @Override
    public void addContent(LcClass controller, Element element) {
        var annotation = element.getAnnotation(ExcelController.class);
        entityQualifiedName = Utils.getElementQualifiedName(element);
        filterName = entityPackageName + ".filter." + element.getSimpleName() + "Filter";

        addExportMethod(controller, annotation);
        addImportMethod(controller, annotation);
    }

    @SneakyThrows
    public void addExportMethod(LcClass controller, ExcelController annotation) {
        var method = new LcMethod(
                new LcModifier(
                        Flags.PUBLIC,
                        new LcAnnotation("org.springframework.web.bind.annotation.GetMapping", Map.of("value", annotation.path())),
                        new LcAnnotation("lombok.SneakyThrows")
                ),
                "VOID",
                "excelExport",
                List.of(
                        new LcVariable(filterName, "queryFilter"),
                        new LcVariable("jakarta.servlet.http.HttpServletResponse", "response")
                ),
                List.of(),
                List.of(
                        new LcApply(
                                "response.setContentType",
                                new LcLiteral("application/vnd.ms-excel")
                        ).exec(),
                        new LcApply(
                                "response.setHeader",
                                new LcLiteral("Content-Disposition"),
                                new LcLiteral("attachment; filename=" + URLEncoder.encode(annotation.exportFilename(), StandardCharsets.UTF_8) + ".xlsx")
                        ).exec(),
                        new LcVariable(
                                "org.springframework.data.domain.PageRequest",
                                "page",
                                new LcApply(
                                        "org.springframework.data.domain.PageRequest.of",
                                        new LcLiteral(0),
                                        new LcLiteral(100)
                                ).getJdkTree()
                        ),
                        new LcVariable(
                                "com.alibaba.excel.write.builder.ExcelWriterSheetBuilder",
                                "builder",
                                new LcApply(List.of(
                                        new LcApply.InvokeInfo("com.alibaba.excel.EasyExcel.write", new LcApply("response.getOutputStream")),
                                        new LcApply.InvokeInfo("head", new LcIdent(entityQualifiedName + ".class")),
                                        new LcApply.InvokeInfo("excelType", new LcIdent("com.alibaba.excel.support.ExcelTypeEnum.XLSX")),
                                        new LcApply.InvokeInfo("sheet", new LcLiteral(annotation.sheetName()))
                                )).getJdkTree()
                        ),
                        new LcVariable("org.springframework.data.domain.Page<" + entityQualifiedName + ">", "list"),
                        new LcDoWhile(
                                List.of(
                                        new LcAssign("list", new LcApply("repository.findAll", new LcIdent("queryFilter"), new LcIdent("page"))).exec(),
                                        new LcIf(new LcApply("list.hasContent"), List.of(new LcApply("builder.doWrite", new LcApply("list.getContent")).exec())),
                                        new LcAssign("page", new LcApply("page.next")).exec()
                                ),
                                new LcApply("list.hasNext")
                        )
                )
        );
        controller.prepend(method);
    }

    public void addImportMethod(LcClass controller, ExcelController annotation) {
        var method = new LcMethod(
                new LcModifier(
                        Flags.PUBLIC,
                        new LcAnnotation("org.springframework.web.bind.annotation.PostMapping", Map.of("value", annotation.path())),
                        new LcAnnotation("lombok.SneakyThrows")
                ),
                "VOID",
                "excelImport",
                List.of(
                        new LcVariable("org.springframework.web.multipart.MultipartFile", "file")
                ),
                List.of(),
                List.of(
                        new LcVariable(
                                "java.util.List<" + entityQualifiedName + ">",
                                "list",
                                new LcApply(List.of(
                                        new LcApply.InvokeInfo("com.alibaba.excel.EasyExcel.read", new LcApply("file.getInputStream")),
                                        new LcApply.InvokeInfo("head", new LcIdent(entityQualifiedName + ".class")),
                                        new LcApply.InvokeInfo("sheet", new LcLiteral(annotation.sheetName())),
                                        new LcApply.InvokeInfo("doReadSync")
                                )).getJdkTree()
                        ),
                        new LcApply("repository.saveAll", new LcIdent("list")).exec()
                )
        );
        controller.prepend(method);
    }
}
